package name.luoyong.shiro.shiroIniCustom.filter;

import java.io.IOException;

import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;


import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.IncorrectCredentialsException;
import org.apache.shiro.authc.UnknownAccountException;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.subject.Subject;
import org.apache.shiro.web.util.SavedRequest;


public class LoginFilter implements Filter {
	
	// constant vars
	protected static final String StrCallbackUrl = "callbackUrl";
	protected static final String StrShiroSavedRequest = "shiroSavedRequest";
	protected static final String StrUsername = "username";
	protected static final String StrPassword = "password";
	
	// params
	private String loginPage = "login.jsp";
	private String errorAccount = "用户名不存在";
	private String errorPassword = "密码错误";
	private String errorLogin = "登陆失败";
	
	
	// gets sets
	
	public String getLoginPage() {
		return loginPage;
	}

	public void setLoginPage(String loginPage) {
		this.loginPage = loginPage;
	}

	public String getErrorAccount() {
		return errorAccount;
	}


	public void setErrorAccount(String errorAccount) {
		this.errorAccount = errorAccount;
	}

	public String getErrorPassword() {
		return errorPassword;
	}

	public void setErrorPassword(String errorPassword) {
		this.errorPassword = errorPassword;
	}

	public String getErrorLogin() {
		return errorLogin;
	}

	public void setErrorLogin(String errorLogin) {
		this.errorLogin = errorLogin;
	}

	// core
	public void init(FilterConfig arg0) throws ServletException {
	}

	public void destroy() {
	}

	public void doFilter(ServletRequest req, ServletResponse resp, FilterChain arg2) throws IOException, ServletException {
		HttpServletRequest request = (HttpServletRequest) req;
		HttpServletResponse response = (HttpServletResponse) resp;
		HttpSession session = request.getSession();
		Subject subject = SecurityUtils.getSubject();
		
		String callbackUrl = getCallbackUrl(request);
		session.removeAttribute(StrShiroSavedRequest);
		request.setAttribute(StrCallbackUrl, callbackUrl);
		
		if(subject.isAuthenticated()) {
			response.sendRedirect(callbackUrl);
			return;
		}
		
		if(request.getMethod().toLowerCase().equals("get")) {
			request.getRequestDispatcher(loginPage).forward(request, response);
			return;
		}
		
		String errorMsg = login(request);
		
		if(errorMsg == null) {
			response.sendRedirect(callbackUrl);
			return;
		} else {
			request.setAttribute("errorMsg", errorMsg);
			request.getRequestDispatcher(loginPage).forward(request, response);
			return;
		}
	}
	
	// service
	protected String login(HttpServletRequest request) {
		String username = request.getParameter(StrUsername);
		String password = request.getParameter(StrPassword);
		boolean isRememberMe = "on".equals(request.getParameter("rememberMe"));
		
		Subject subject = SecurityUtils.getSubject();
		UsernamePasswordToken token = new UsernamePasswordToken(username, password);
		if(isRememberMe) {
			token.setRememberMe(true);
		}
		
		String errorMsg = null;
		
		try {
			subject.login(token);
		} catch(UnknownAccountException e) {
			errorMsg = errorAccount;
		} catch(IncorrectCredentialsException e) {
			errorMsg = errorPassword;
		} catch(AuthenticationException e) {
			errorMsg = errorLogin;
		}
		
		return errorMsg;
	}

	protected String getCallbackUrl(HttpServletRequest request) {
		HttpSession session = request.getSession();
		SavedRequest savedRequest = (SavedRequest) session.getAttribute(StrShiroSavedRequest);
		
		if(savedRequest != null) {
			return savedRequest.getRequestUrl();
		}
		
		String callbackUrl = request.getParameter(StrCallbackUrl);
		if(callbackUrl != null) {
			return callbackUrl;
		}
		
		callbackUrl = request.getHeader("Referer");
		if(callbackUrl != null) {
			return callbackUrl;
		}
		
		return "/";
	}
	

}
